// Effective C++ 条款22：将变量声明为private
// 核心原则
// 这条款的核心思想是：将成员变量声明为private，而不是public或protected。
// 主要理由
// 1.封装性：私有成员变量提供了更好的封装，使得类的实现细节对外部代码隐藏。
// 2.访问控制：通过getter和setter方法控制对成员变量的访问，可以：
//      实现只读访问（只提供getter）
//      实现只写访问（只提供setter）
//      在读写时添加验证逻辑
//      在修改时触发其他操作（如通知观察者）
// 3.不变式维护：可以在setter方法中确保类的不变式（invariants）得到维护。
// 4.向后兼容性：如果将来需要改变实现，private成员变量允许你在不破坏客户代码的情况下进行修改。

// 代码示例
// 不好的做法：
class Person
{
public:
    std::string name;
    int age;
};

// 好的做法：
class Person
{
private:
    std::string name;
    int age;

public:
    // Getters
    const std::string &getName() const { return name; }
    int getAge() const { return age; }

    // Setters
    void setName(const std::string &newName) { name = newName; }
    void setAge(int newAge)
    {
        if (newAge >= 0)
        { // 验证逻辑
            age = newAge;
        }
    }
};

// 虽然直觉上我们可能认为在继承关系中应该将变量声明为protected，
// 但Effective C++实际上建议即使在继承关系中也应该将成员变量声明为private而非protected。让我解释一下原因：
// 为什么继承中也应该使用private而非protected成员变量
// 主要原因
// 1.封装的破坏：
//      protected成员变量对所有派生类都是可见的，这意味着基类的实现细节被暴露给了所有派生类
//      如果基类的实现需要改变，所有依赖于这些protected成员变量的派生类都可能需要修改
// 2.基类与派生类的耦合：
//      protected成员变量创建了基类和派生类之间的紧密耦合
//      派生类可以直接访问和修改基类的状态，这违反了封装原则
// 3.维护难度增加：
//      当基类的protected成员变量被多个派生类直接使用时，修改这些变量变得非常困难
//      你需要检查所有派生类以确保修改不会破坏它们的功能

// 不推荐的方式
class Base
{
protected:
    int data; // 派生类可以直接访问
};

class Derived : public Base
{
public:
    void someFunction()
    {
        data = 42; // 直接访问基类的成员变量
    }
};

// 推荐的方式
class Base
{
private:
    int data;

protected:
    // 提供protected的访问方法给派生类使用
    int getData() const { return data; }
    void setData(int newValue) { data = newValue; }
};

class Derived : public Base
{
public:
    void someFunction()
    {
        setData(42); // 通过基类提供的方法访问
    }
};

// 这种设计的优点
// 控制访问方式：基类可以决定子类如何访问其内部状态
// 实现细节隐藏：子类不需要知道基类如何存储数据
// 版本兼容性：基类可以改变内部实现而不影响子类
// 行为一致性：可以在protected方法中强制执行特定规则或验证
// 这正是Effective C++所推荐的设计方式，它在提供继承灵活性的同时保持了良好的封装性。